package com.iretailer.report.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.iretailer.report.dto.PageResult;
import com.iretailer.report.dto.QueryOption;
import com.iretailer.report.mapper.BusinessTimeMapper;
import com.iretailer.report.model.*;
import com.iretailer.report.util.StringUtil;
import com.iretailer.report.util.TimeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.time.*;
import java.util.*;

/**
 * @Auther: xjw
 * @Date: 2019/1/24 10:03
 * @Description:
 */
@Service
public class BusinessTimeService extends ServiceImpl<BusinessTimeMapper, BusinessTimes> {
    @Autowired
    private BusinessTimeMapper businessTimeMapper;
    @Autowired
    private CategoriesService categoriesService;
    @Autowired
    private BusinessTimeMallService businessTimeMallService;

    public PageResult<BusinessTimeCompany> gridBusinessTimes(List<String> companyId, String companyName, QueryOption queryOption) {
        Page page = new Page<BusinessTimeCompany>(1, Long.MAX_VALUE);
        QueryWrapper<BusinessTimeCompany> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("1", 1);
        if (companyId != null) {
            queryWrapper.in("companyId", companyId);
        }
        if (companyName != null) {
            queryWrapper.like("companyName", companyName);
        }
        queryOption.judge(page, queryWrapper);
        queryWrapper.orderByAsc("CompanyId");
        businessTimeMapper.selectPageBusinessTimeCompanyName(page, queryWrapper);
//        businessTimeMapper.selectPage(page, queryWrapper);
        return new PageResult<>(page.getTotal(), page.getRecords());
    }

    /***
     * 根据 mallIds 获取 startTime 和 endTime 最长
     * @param mallIds
     * @return
     */
    public BusinessTimes selectMaxBusinessTimes(List<String> mallIds) {

        BusinessTimes result = new BusinessTimes();
        List<BusinessTimes> businessTimes = selectByMallIds(mallIds);
        if (businessTimes != null && businessTimes.size() > 0) {
            BusinessTimes startTime = businessTimes.stream().min(Comparator.comparing(BusinessTimes::getStartTime)).get();
            BusinessTimes endTime = businessTimes.stream().max(Comparator.comparing(BusinessTimes::getEndTime)).get();
            result.setStartTime(startTime.getStartTime());
            result.setEndTime(endTime.getEndTime());
        } else {
            result.setStartTime(LocalTime.of(0, 0, 0));
            result.setEndTime(LocalTime.of(23, 59, 59));
        }
        return result;
    }

    public List<BusinessTimes> selectByMallIds(List<String> mallIds) {
        return businessTimeMapper.selectByMallIds(mallIds);
    }

    /**
     * 根据 mallId 查询出 其所有的 BusinessTime
     */
    public List<BusinessTimes> selectByMallId(String mallId) {
        return businessTimeMapper.selectByMallId(mallId);
    }

    @Cacheable(value = "filterBusinessTime", key = "#mallId")
    public MallBusinessTime filterBusinessTime(String mallId, LocalDateTime dateTime) {

        List<MallBusinessTime> businessTimes = businessTimeMallService.selectMallBusinessTime(new QueryWrapper<MallBusinessTime>()
                .eq("MallId", mallId)
                .orderByAsc("ranked"));
        if (businessTimes != null && businessTimes.size() > 0) {
            for (MallBusinessTime b : businessTimes) {
                ZonedDateTime zonedDateTime = ZonedDateTime.of(dateTime, ZoneId.of(b.getTimeZone()));
                String weekDay = TimeUtil.getWeekOfZonedDateTime(zonedDateTime);
                if (b.getWeekdays().indexOf(weekDay) > -1) {
                    return b;
                }
            }
        }
        return new MallBusinessTime();
    }

    public Map<String, MallBusinessTime> filterBusinessTime(String mallId, List<String> dates) {
        List<MallBusinessTime> businessTimes = businessTimeMallService.selectMallBusinessTime(new QueryWrapper<MallBusinessTime>()
                .eq("MallId", mallId)
                .orderByAsc("ranked"));
        Map<String, MallBusinessTime> resultMap = new HashMap<>();
        if (businessTimes != null && businessTimes.size() > 0) {
            for (String date : dates) {
                for (MallBusinessTime b : businessTimes) {
                    LocalDate dateL = TimeUtil.parse_LocalDate(date);
                    if (!dateL.isBefore(TimeUtil.parse_LocalDate(b.getStartDate())) && !dateL.isAfter(TimeUtil.parse_LocalDate(b.getEndDate()))) {
                        String weekDay = TimeUtil.getWeekOfLocalDate(dateL);
                        if (b.getWeekdays().indexOf(weekDay) > -1) {
                            resultMap.put(date, b);
                            break;
                        }
                    }
                }
            }
        }
        return resultMap;
    }

    public MallBusinessTime filterBusinessTime(String mallId, String date) {
        List<MallBusinessTime> businessTimes = businessTimeMallService.selectMallBusinessTime(new QueryWrapper<MallBusinessTime>()
                .eq("MallId", mallId)
                .orderByAsc("ranked"));
        if (businessTimes != null && businessTimes.size() > 0) {
            for (MallBusinessTime b : businessTimes) {
                LocalDate dateL = TimeUtil.parse_LocalDate(date);
                if (!dateL.isBefore(TimeUtil.parse_LocalDate(b.getStartDate())) && !dateL.isAfter(TimeUtil.parse_LocalDate(b.getEndDate()))) {
                    String weekDay = TimeUtil.getWeekOfLocalDate(dateL);
                    if (b.getWeekdays().indexOf(weekDay) > -1) {
                        return b;
                    }
                }
            }
        }
        return new MallBusinessTime();

    }

    /**
     * 新增   更新
     */
    @Override
    @CacheEvict(value = {"filterBusinessTime"}, allEntries = true)
    public boolean saveOrUpdate(BusinessTimes businessTimes) {
        if (StringUtil.notEmpty(businessTimes.getTimeType())) {
            Categories categories = categoriesService.getById(businessTimes.getTimeType());
            if (categories != null) {
                businessTimes.setTimeTypeName(categories.getName());
            }
        }
        if (!StringUtil.notEmpty(businessTimes.getTimeTypeName())) {
            return false;
        }
        if (StringUtil.notEmpty(businessTimes.getId())) {
            businessTimeMapper.updateById(businessTimes);
        } else {
            businessTimeMapper.insert(businessTimes);
        }
        return true;
    }

    /**
     * @param businessTimes
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRED)
    @CacheEvict(value = {"filterBusinessTime"}, allEntries = true)
    public boolean creatBusiness(BusinessTimes businessTimes, String oldBusinessTimeId, String mallId) {
        // 新建一个 business time
        businessTimeMapper.insert(businessTimes);
        // 删除 老的关联
        deleteBusinessTimeMallByBusinessTimeIdAndMallId(oldBusinessTimeId, mallId);
        // 插入新的关联
        businessTimeMapper.insertBusinessTimeMalls(businessTimes.getId(), Arrays.asList(mallId));
        return true;
    }


    public boolean deleteBusinessTimeByIds(List<Long> ids) {
        if (!ids.isEmpty()) {
            businessTimeMapper.deleteBusinessTimeByIds(ids);
            return true;
        } else {
            return false;
        }
    }

    public boolean deleteBusinessTimeMallByBusinessTimeIdAndMallId(String businessTimeId, String mallId) {
        businessTimeMapper.deleteBusinessTimeMallByBusinessTimeIdAndMallId(businessTimeId, mallId);
        return true;
    }

    /**
     * 根据主键进行删除
     */
    @CacheEvict(value = {"filterBusinessTime"}, allEntries = true)
    public boolean deleteByIds(List<String> ids) {
        List<BusinessTimeMall> businessTimeMalls = businessTimeMallService.list(new QueryWrapper<BusinessTimeMall>().lambda().in(BusinessTimeMall::getBusinesstimeId, ids));
        if (businessTimeMalls != null && businessTimeMalls.size() > 0) {
            return false;
        } else {
            businessTimeMapper.deleteBatchIds(ids);
            return true;
        }
    }

    /**
     * 根据 主键 更新 mallIds 的关联
     */
    @CacheEvict(value = {"filterBusinessTime"}, allEntries = true)
    @Transactional(propagation = Propagation.REQUIRED)
    public boolean saveBusinessTimeMalls(String id, List<String> mallIds) {
        if (StringUtil.notEmpty(id) && mallIds != null) {
            businessTimeMapper.deleteBusinessTimeMallsByBusinessTimeId(id);
            if (mallIds.size() > 0) {
                businessTimeMapper.insertBusinessTimeMalls(id, mallIds);
            }
            return true;
        } else {
            return false;
        }
    }

    /**
     * 根据 userId 查询出 user 下的 business
     */
    public List<BusinessTimes> selectBusinessTimeByUserId(String userId) {
        return businessTimeMapper.selectByUserId(userId);
    }


    public boolean insertBusinessTimeMalls(String id, List<String> mallIds) {
        return businessTimeMapper.insertBusinessTimeMalls(id, mallIds) > 0;
    }
}
